home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995 August: Tool Chest / Dev.CD Aug 95 TC / Dev.CD Aug 95 TC.toast / Sample Code / RAMDisk 1.1 / Sources / RamDRVR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-13  |  10.7 KB  |  397 lines  |  [TEXT/MPS ]

  1. #define __DebugVersion    1
  2. /*
  3. **    Apple Macintosh Developer Technical Support
  4. **
  5. **    RamDRVR.c: Driver for RamDisk Sample
  6. **
  7. **    by Gordon Sheridan and Jim Luther
  8. **  modified by Brian Bechtel
  9. **
  10. **    File:        RamDRVR.c
  11. **
  12. **    Copyright © 1992-1994 Apple Computer, Inc.
  13. **    All rights reserved.
  14. **
  15. **    You may incorporate this sample code into your applications without
  16. **    restriction, though the sample code has been provided "AS IS" and the
  17. **    responsibility for its operation is 100% yours.  However, what you are
  18. **    not permitted to do is to redistribute the source as "DTS Sample Code"
  19. **    after having made changes. If you're going to re-distribute the source,
  20. **    we require that you make it clear in the source that the code was
  21. **    descended from Apple Sample Code, but that you've made changes.
  22. **
  23. **    Change History (most recent first):
  24. **
  25. **    Change History (most recent first):
  26. **
  27. **         <6>    06/10/94    BL°B    Converted to work with Symantec as well.
  28. **         <5>    05/19/94    BL°B    Converted to work with Metrowerks.  Added 
  29. **                                     conditionally compiled main routine for Metrowerks.
  30. **         <4>    10/23/93    JML        Added check for valid globals before accepting
  31. **                                     Prime, Control, or Status calls (except the control
  32. **                                    and status routines that get and set the globals).
  33. **         <3>    10/14/93    JML        Added support for the following Control and Status
  34. **                                    calls: physicalIconCC, mediaIconCC, driveInfoCC,
  35. **                                    formatListSC.  driveStatusSC now returns a copy
  36. **                                    of our DrvQEl.  Prime, Control and Status now checks
  37. **                                    that ioVRefNum = our drive number.  Prime now updates
  38. **                                    dCtlPosition so I/O using fsFromMark will work. All
  39. **                                    debugging code now hidden with "Panic" macros. Prime
  40. **                                    now checks for block aligned I/O (since this is a
  41. **                                    block device).  All calls now return appropriate error
  42. **                                    results.
  43. **        <2+>     7/26/93    gs        Set result = noErr for Status csCode = 8.
  44. **         <2>     6/29/93    gs        Return Drive Stats, miscellaneous clean up.
  45. **         <1>     6/13/93    gs        Allocate space for disk from driver. Clean up comments.
  46. **         <0>     1/17/90    gs        11:58 PM, first version.
  47. **/
  48.  
  49.  
  50. #include "RamDisk.h"
  51.  
  52. /*****************************************************************************/
  53. /*
  54. **    Prototypes
  55. */
  56.  
  57. pascal    OSErr    DRVROpen    (ParmBlkPtr pb, DCtlPtr dce);
  58. pascal    OSErr    DRVRPrime    (ParmBlkPtr pb, DCtlPtr dce);
  59. pascal    OSErr    DRVRControl    (ParmBlkPtr pb, DCtlPtr dce);
  60. pascal    OSErr    DRVRStatus    (ParmBlkPtr pb, DCtlPtr dce);
  61. pascal    OSErr    DRVRClose    (ParmBlkPtr pb, DCtlPtr dce);
  62.  
  63. /*****************************************************************************/
  64.  
  65. pascal    OSErr    DRVROpen (ParmBlkPtr pb, DCtlPtr dce)
  66. {
  67.     DrvrGlobals       *globe;
  68.     OSErr            result = noErr;
  69.  
  70. #pragma unused (pb)
  71.  
  72.     /* set device flags because Device Mgr copied header */
  73.     dce->dCtlFlags |= dCtlEnable | dStatEnable | dWritEnable | dReadEnable | dNeedLock;
  74.     dce->dCtlDelay = 0;
  75.  
  76.  
  77.     if (!dce->dCtlStorage)    /* is driver already open ? */
  78.     {
  79.         dce->dCtlStorage = (Handle)NewPtrSysClear(sizeof(DrvrGlobals));
  80.         if (!(Ptr)dce->dCtlStorage)
  81.         {
  82.             result = MemError();
  83.             Panic("\pDRVROpen:NewPtr returned nil");
  84.         }
  85.             
  86.         globe = (DrvrGlobals *)dce->dCtlStorage;
  87.     }
  88.     else
  89.         Panic("\pDRVROpen:2nd open attempt");
  90.     
  91.     return (result);
  92. }
  93.  
  94. /*****************************************************************************/
  95.  
  96. pascal    OSErr    DRVRPrime (ParmBlkPtr pb, DCtlPtr dce)
  97. {
  98.     DrvrGlobals        *globe;
  99.     unsigned long    position;
  100.     unsigned long    count;
  101.     short            calltype;
  102.     OSErr            result;
  103.  
  104.     if (dce->dCtlStorage)
  105.     {
  106.         globe = (DrvrGlobals *)dce->dCtlStorage;
  107.         
  108.         if (globe->driveNumber != 0) /* accept no calls, before the globals are initialized */
  109.         {
  110.             position = dce->dCtlPosition;
  111.             count = pb->ioParam.ioReqCount;
  112.             
  113.             /* Preflight the request for block alignment, size, and range */
  114.             if (((position % 512) == 0) &&
  115.                 ((count % 512) == 0) &&
  116.                 ((count + position) <= globe->ramSize))
  117.             {
  118.                 calltype = 0x00FF & pb->ioParam.ioTrap;
  119.                 switch(calltype)
  120.                 {
  121.                     case aRdCmd:
  122.                         /* Read the data */
  123.                         BlockMove(&globe->ramDisk[position], pb->ioParam.ioBuffer, count);
  124.                         break;
  125.                     case aWrCmd:
  126.                         /* Write the data */
  127.                         BlockMove(pb->ioParam.ioBuffer, &globe->ramDisk[position], count);
  128.                         break;
  129.                     default:        
  130.                         Panic("\pDRVRPrime: Call wasn't _Read or _Write");
  131.                         break;
  132.                 }
  133.                 
  134.                 dce->dCtlPosition += count;        /* Update the position */
  135.                 pb->ioParam.ioActCount = count;    /* Return the actual count */
  136.                 
  137.                 result = noErr;
  138.             }
  139.             else
  140.             {
  141.                 Panic("\pDRVRPrime: Invalid block request");
  142.                 result = paramErr;
  143.             }
  144.         }
  145.         else
  146.         {
  147.             Panic("\pDRVRPrime: Globals aren't initialized");
  148.             result = nsDrvErr;
  149.         }
  150.     }
  151.     else
  152.     {
  153.         Panic("\pDRVRPrime: No dCtlStorage");
  154.         result = notOpenErr;
  155.     }
  156.     
  157.     return (result);
  158. }
  159.  
  160. /*****************************************************************************/
  161.  
  162. pascal    OSErr    DRVRControl (ParmBlkPtr pb, DCtlPtr dce)
  163. {
  164.     DrvrGlobals       *globe;
  165.     OSErr            result = controlErr;
  166.     long            size;
  167.     long            i;
  168.     
  169.     if (dce->dCtlStorage)
  170.     {
  171.         globe = (DrvrGlobals *)dce->dCtlStorage;
  172.         
  173.         /* Accept only setGlobalsCC call, before the globals are initialized */
  174.         if (pb->cntrlParam.csCode == setGlobalsCC)
  175.         {
  176.             /* Initialize DrvrGlobals */
  177.             BlockMove( *(Ptr *)pb->cntrlParam.csParam,(Ptr)globe, sizeof(DrvrGlobals));
  178.             result = noErr;
  179.         }
  180.         else if (globe->driveNumber != 0)
  181.         {
  182.             switch(pb->cntrlParam.csCode)
  183.             {
  184.                 case killIOCC:
  185.                     /* What's there to kill?  A BlockMove? sure... */
  186.                     Panic("\pDRVRControl: KillIO on Ram Disk?");
  187.                     break;
  188.                 
  189.                 case verifyDiskCC:
  190.                     result = noErr;
  191.                     break;
  192.                 
  193.                 case formatDiskCC:
  194.                     /* zero out ram disk memory */
  195.                     size = globe->ramSize / 4;
  196.                     for (i = 0 ; i < size; i++)
  197.                         ((long *)globe->ramDisk)[i] = 0;
  198.                     result = noErr;
  199.                     break;
  200.                         
  201.                 case ejectDiskCC:
  202.                      break;
  203.                             
  204.                 case physicalIconCC:
  205.                     /* return pointer to icon and where string */
  206.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->physicalIcon;
  207.                     result = noErr;
  208.                     break;
  209.                 
  210.                 case mediaIconCC:
  211.                     /* return pointer to icon and where string */
  212.                     *(Ptr *)pb->cntrlParam.csParam = (Ptr)globe->mediaIcon;
  213.                     result = noErr;
  214.                     break;
  215.     
  216.                 case driveInfoCC:
  217.                     /* high word (bytes 2 & 3) clear */
  218.                     /* byte 1 = primary + fixed media + internal */
  219.                     /* byte 0 = drive type (0x10 = RAM disk) */
  220.                     *(unsigned long *)pb->cntrlParam.csParam = 0x00000410;
  221.                     result = noErr;
  222.                     break;
  223.                 
  224.                 case 24:    /* ••• Return SCSI csCode Partition Size */
  225.                     *(unsigned long *)pb->cntrlParam.csParam = globe->ramSize >> 9;
  226.                     result = noErr;
  227.                     break;
  228.     
  229.                 case accRun:
  230.                     result = noErr;
  231.                     break;
  232.     
  233.                 default:
  234.                     Panic("\pUnrecognized control call");
  235.                     break;
  236.             }
  237.         }
  238.         else
  239.         {
  240.             Panic("\pDRVRControl: Globals not initialized");
  241.         }
  242.     }
  243.     else
  244.     {
  245.         Panic("\pDRVRControl: No dCtlStorage");
  246.         result = notOpenErr;
  247.     }
  248.         
  249.     return (result);
  250. }
  251.  
  252. /*****************************************************************************/
  253.  
  254. pascal    OSErr    DRVRStatus (ParmBlkPtr pb, DCtlPtr dce)
  255. {
  256.     DrvrGlobals            *globe;
  257.     OSErr                result = statusErr;
  258.     DrvSts                *driveStats;
  259.     DrvQElPtr            driveQEl;
  260.     
  261.     if (dce->dCtlStorage)
  262.     {
  263.         globe = (DrvrGlobals *)dce->dCtlStorage;
  264.     
  265.         /* Accept only getGlobalsSC call, before the globals are initialized */
  266.         if (pb->cntrlParam.csCode == getGlobalsSC)
  267.         {
  268.             *(long *)pb->cntrlParam.csParam = globe->ramSize;
  269.             if (globe->ramSize == 0)
  270.             {
  271.                 Panic("\pDRVRStatus: ramSize is zero");
  272.             }
  273.             result = noErr;
  274.         }
  275.         else if (globe->driveNumber != 0)
  276.         {
  277.             switch(pb->cntrlParam.csCode)
  278.             {
  279.                 case driveStatusSC:
  280.                     if (pb->cntrlParam.ioVRefNum != globe->driveNumber)
  281.                         break;
  282.                     
  283.                     /* Drive Stats... */
  284.                     driveStats = (DrvSts *)pb->cntrlParam.csParam;
  285.                     driveStats->track        = 0;    /* not applicable */
  286.                     driveStats->writeProt    = 0;    /* write enabled */
  287.                     driveStats->diskInPlace    = 0x08;    /* non-ejectable */
  288.                     driveStats->installed    = 1;    /* drive installed */
  289.                     driveStats->sides        = 0;    /* not applicable */
  290.                     driveStats->twoSideFmt    = 0;    /* not applicable */
  291.                     driveStats->needsFlush    = 0;    /* not applicable */
  292.                     driveStats->diskErrs    = 0;    /* not applicable */
  293.                     
  294.                     /* Copy qLink through dQFSID from our DrvQEl */
  295.                     driveQEl = (DrvQElPtr)(GetDrvQHdr()->qHead);
  296.                     while(driveQEl != nil)
  297.                     {
  298.                         if (driveQEl->dQDrive == globe->driveNumber)
  299.                         {
  300.                             driveStats->qLink = driveQEl->qLink;
  301.                             driveStats->qType = driveQEl->qType;
  302.                             driveStats->dQDrive = driveQEl->dQDrive;
  303.                             driveStats->dQRefNum = driveQEl->dQRefNum;
  304.                             driveStats->dQFSID = driveQEl->dQFSID;
  305.     
  306.                             break; /* while(driveQEl != nil) */
  307.                         }
  308.                         driveQEl = (DrvQElPtr)(driveQEl->qLink);
  309.                     }
  310.                     
  311.                     result = noErr;
  312.                     break;
  313.                 
  314.                 default:
  315.                     break;
  316.             }
  317.         }
  318.         else
  319.         {
  320.             Panic("\pDRVRStatus: Globals not initialized");
  321.         }
  322.     }
  323.     else
  324.     {
  325.         Panic("\pDRVRStatus: No dCtlStorage");
  326.         result = notOpenErr;
  327.     }
  328.  
  329.     return (result);
  330. }
  331.  
  332. /*****************************************************************************/
  333.  
  334. pascal    OSErr    DRVRClose (ParmBlkPtr pb, DCtlPtr dce)
  335. {
  336.     DrvrGlobals    *globe;
  337.  
  338. #pragma unused (pb)
  339.         
  340.     if (dce->dCtlStorage)
  341.     {
  342.         globe = (DrvrGlobals *)dce->dCtlStorage;
  343.         
  344.         if (globe->ramDisk)
  345.             DisposPtr(globe->ramDisk);
  346.         
  347.         DisposPtr((Ptr)dce->dCtlStorage);
  348.     }
  349.     
  350.     return (noErr);
  351. }
  352.  
  353. /*****************************************************************************/
  354. #if (defined(__MWERKS__) || defined(THINK_C))
  355. /*****************************************************************************/
  356. /* Metrowerks specific main routine.  This isn't used in MPW; we use an      */
  357. /* assembly language header instead.                                         */
  358. /*****************************************************************************/
  359.  
  360. OSErr main(ParmBlkPtr paramBlock,DCtlPtr devCtlEnt,short dispatch)
  361. {
  362. //
  363. //    Here A4 is already setup to point to our data segment. There is no need
  364. //    to call long oldA4=SetCurrentA4();/SetA4(oldA4); as in code resources.
  365. //
  366. //    However you have to still have to use "#include <SetupA4.h>;RememberA4();..."
  367. //    when using callback functions.
  368. //
  369. // If your routine returns 1 (asynch request can't be completed right away)
  370. // the Metrowerks startup code will correctly jump to jIODone.  You don't need
  371. // to worry about this issue in this driver.
  372. //
  373.     OSErr    err = noErr;
  374.     
  375.     switch(dispatch)
  376.     {
  377.     case 0: //    Open
  378.         err = DRVROpen(paramBlock, devCtlEnt);
  379.         break;
  380.     case 1: //    Prime        return 1 if async request cannot be completed right away
  381.         err = DRVRPrime(paramBlock, devCtlEnt);
  382.         break;
  383.     case 2: //    Control        return 1 if async request cannot be completed right away
  384.         err = DRVRControl(paramBlock, devCtlEnt);
  385.         break;
  386.     case 3: //    Status        return 1 if async request cannot be completed right away
  387.         err = DRVRStatus(paramBlock, devCtlEnt);
  388.         break;
  389.     case 4: //    Close
  390.         err = DRVRClose(paramBlock, devCtlEnt);
  391.         break;
  392.     }
  393.     return err;
  394. }
  395. #endif // __MWERKS__ or THINK_C
  396.  
  397.